#define _CRT_SECURE_NO_WARNINGS

//typedef int StackType;
//typedef struct Stack
//{
//	StackType* arr;
//	int top;
//	int capacity;
//}Stack;
//
//void StackInit(Stack* ps);
//
//void StackPrint(Stack* ps);
//
//void StackCheck(Stack* ps);
//
//void StackDestroy(Stack* ps);
//
//void StackPush(Stack* ps, StackType val);
//
//void StackPop(Stack* ps);
//
//StackType StackTop(Stack* ps);
//
//int StackSize(Stack* ps);
//
//bool StackEmpty(Stack* ps);
//
//void StackInit(Stack* ps)
//{
//	assert(ps);
//	ps->arr = NULL;
//	ps->top = ps->capacity = 0;
//}
//
//// void StackPrint(Stack* ps)
//// {
//// 	assert(ps);
//// 	int i = 0;
//// 	for (i = 0; i < ps->top; i++)
//// 	{
//// 		printf("%d ", ps->arr[i]);
//// 	}
//// 	printf("\n");
//// }
//
//void StackDestroy(Stack* ps)
//{
//	assert(ps);
//	free(ps->arr);
//	ps->arr = NULL;
//	ps->top = ps->capacity = 0;
//}
//
//void StackCheck(Stack* ps)
//{
//	assert(ps);
//	if (ps->top == ps->capacity)
//	{
//		int newcapacity = ps->top == 0 ? 4 : 2 * ps->capacity;
//		StackType* tmp = (StackType*)realloc(ps->arr, newcapacity * sizeof(Stack));
//		if (tmp == NULL)
//		{
//			perror("realloc fail\n");
//			exit(-1);
//		}
//		ps->arr = tmp;
//		ps->capacity = newcapacity;
//	}
//}
//
//void StackPush(Stack* ps, StackType val)
//{
//	assert(ps);
//	StackCheck(ps);
//	ps->arr[ps->top] = val;
//	ps->top++;
//}
//
//void StackPop(Stack* ps)
//{
//	assert(ps);
//	if (!StackEmpty(ps))
//	{
//		(ps->top)--;
//	}
//}
//
//StackType StackTop(Stack* ps)
//{
//	return ps->arr[ps->top - 1];
//}
//
//int StackSize(Stack* ps)
//{
//	assert(ps);
//
//	return ps->top;
//}
//
//bool StackEmpty(Stack* ps)
//{
//	assert(ps);
//	if (ps->top == 0)
//	{
//		return true;
//	}
//	return false;
//	//return ps->top == 0;
//}
//
//typedef struct {
//	Stack PushSL;
//	Stack PopSL;
//} MyQueue;
//
//MyQueue* myQueueCreate() {
//	MyQueue* obj = (MyQueue*)malloc(sizeof(MyQueue));
//	StackInit(&obj->PushSL);
//	StackInit(&obj->PopSL);
//
//	return obj;
//}
//
//void myQueuePush(MyQueue* obj, int x) {
//	StackPush(&obj->PushSL, x);
//}
//
//int myQueuePop(MyQueue* obj) {
//	if (StackEmpty(&obj->PopSL))
//	{
//		while (!StackEmpty(&obj->PushSL))
//		{
//			StackPush(&obj->PopSL, StackTop(&obj->PushSL));
//			StackPop(&obj->PushSL);
//		}
//	}
//
//	int top = StackTop(&obj->PopSL);
//	StackPop(&obj->PopSL);
//
//	return top;
//}
//
//int myQueuePeek(MyQueue* obj) {
//	if (StackEmpty(&obj->PopSL))
//	{
//		while (!StackEmpty(&obj->PushSL))
//		{
//			StackPush(&obj->PopSL, StackTop(&obj->PushSL));
//			StackPop(&obj->PushSL);
//		}
//	}
//
//	return StackTop(&obj->PopSL);
//}
//
//bool myQueueEmpty(MyQueue* obj) {
//	return StackEmpty(&obj->PushSL) && StackEmpty(&obj->PopSL);
//}
//
//void myQueueFree(MyQueue* obj) {
//	StackDestroy(&obj->PushSL);
//	StackDestroy(&obj->PopSL);
//	free(obj);
//}

/**
* Your MyQueue struct will be instantiated and called as such:
* MyQueue* obj = myQueueCreate();
* myQueuePush(obj, x);

* int param_2 = myQueuePop(obj);

* int param_3 = myQueuePeek(obj);

* bool param_4 = myQueueEmpty(obj);

* myQueueFree(obj);
*/
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>

typedef struct ListNode
{
	int val;
	struct ListNode* next;
}ListNode;

typedef struct {
	struct ListNode* head;
	struct ListNode* tail;
	int capacity;
	int size;
} MyCircularQueue;

struct ListNode* QueueCreateNode(int value)
{
	struct ListNode* newnode = (struct ListNode*)malloc(sizeof(struct ListNode));
	if (newnode == NULL)
	{
		perror("malloc fail\n");
		exit(-1);
	}
	newnode->next = NULL;
	newnode->val = value;

	return newnode;
}

MyCircularQueue* myCircularQueueCreate(int k) {
	MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	obj->head = obj->tail = NULL;
	obj->capacity = k;
	obj->size = 0;

	return obj;
}

bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
	if (obj->size == obj->capacity)
		return false;

	struct ListNode* newnode = QueueCreateNode(value);
	if (obj->head == NULL)
	{
		obj->head = obj->tail = newnode;
	}
	else
	{
		obj->tail->next = newnode;
		obj->tail = newnode;
	}
	obj->size++;

	return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
	if (obj->size == 0)
		return false;

	struct ListNode* del = obj->head->next;
	free(obj->head);
	obj->head = del;
	obj->size--;

	return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
	if (obj->size == 0)
	{
		return -1;
	}
	return obj->head->val;
}

int myCircularQueueRear(MyCircularQueue* obj) {
	if (obj->size == 0)
	{
		return -1;
	}
	return obj->tail->val;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
	return obj->size == 0;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
	return obj->size == obj->capacity;
}

void myCircularQueueFree(MyCircularQueue* obj) {
	struct ListNode* cur = obj->head;
	while (cur)
	{
		struct ListNode* next = cur->next;
		free(cur);
		cur = next;
	}
	free(obj);
}

int main()
{
	MyCircularQueue* sl = myCircularQueueCreate(4);
	myCircularQueueEnQueue(sl, 3);
}